import java.util.*;

import javax.xml.crypto.Data;

/**
 * Represents a list which the value of the ith element is 
 * the color of the ith node in the graph coloring problem 
 * @author matan
 */
public class Chromosome implements Comparable<Chromosome>{

	//Data members
	private double _fitness;			///< fitness of chromosome
	private List<Integer> _data;	///< list of node colors
	
	/**
	 * Constructor
	 * @param fitness fitness of current chromosome
	 * @param data gene stream of current chromosome
	 */
	public Chromosome(double fitness, List<Integer> data) {
		_fitness = fitness;
		_data = new ArrayList<Integer>(data);
	}
	
	public Chromosome(List<Integer> data) {
		this(0, data);
	}

	public int compareTo(Chromosome c) {
		return (int)( -this.getFitness() + c.getFitness());
	}
	
	/**
	 * Constructor: creates new random gene chromosome of given length
	 * @param length length of current chromosome
	 * @param numColors total number of available colors
	 */
	public Chromosome(int length) {
		_data = new ArrayList<Integer>(length);
		
		//create a new random color for each node
		for (int i = 0; i < length; ++i) {
			_data.add(GeneticUtils.rnd.nextInt(GeneticUtils.NUM_COLORS));
		}
	}
	
	/**
	 * count usage of 4th color
	 * @return times that 4th color was used
	 */
	public int get4Count() {
		int i=0;
		for (int j=0;j<_data.size();++j)
			if (_data.get(j) == 3)
				++i;
		return i;
	}
	
	/**
	 * Gets the length of the chromosome
	 * @return length of the chromosome
	 */
	public int getLength() {
		return _data.size();
	}
	
	/**
	 * Gets the color of the specified node
	 * @param index index of specified node
	 * @return the color of selected node
	 */
	public int getData(int index) {
		return _data.get(index);
	}
	
	/**
	 * Sets the color of the specified node
	 * @param index index of specified node
	 * @param value the new color of selected node
	 */
	public void setData(int index, int value) {
		_data.set(index, value);
	}
	
	public void setData(int index, List<Integer> value) {
		for (int i = 0; i < value.size(); ++i)
			_data.set(i + index, value.get(i));
	}
	
	/**
	 * Clones current chromosome
	 * @return a new clone of the chromosome
	 */
	public Chromosome clone() {
		return new Chromosome(_fitness, _data);
	}
	
	/**
	 * Gets the fitness of current chromosome
	 * @return fitness of current chromosome
	 */
	public double getFitness() {
		return _fitness;
	}
	
	/**
	 * Sets the fitness of current chromosome
	 * @param fitness fitness to be set
	 */
	public void setFitness(double fitness) {
		_fitness = fitness;
	}
	
	public List<Integer> getRange(int to) {
		return this.getRange(0, to);
	}
	
	/**
	 * Gets gene data from chromosome
	 * @param from start index
	 * @param to end index
	 * @return sequence between input indices
	 */
	public List<Integer> getRange(int from, int to) {
		return new LinkedList<Integer>(_data.subList(from, to));
	}
	
	public List<Integer> getAll() {
		return getRange(0, _data.size());
	}
	
	@Override
	public String toString() {
		return _data.toString();
	}
}